# Friends grapher
# by Cee Pee

from deps import DotGraph
import random
import subprocess
import string
import forumapi

def settings(settings):
	settings.add_option("-u", "--users", type="list", help="user IDs to work on", metavar="IDS")
	settings.add_option("--recursion", type="int", default=0, help="how deep to find users' friends", metavar="DEPTH")
	settings.add_option("--all", action="store_true", default=False, help="work on all users")
	settings.add_option("--max-user", type="int", help="with --all, end at this user instead of when a user has no profile")

def main(me, options, args):
	users = []
	if options.users:
		for user in options.users:
			try:
				users.append(forumapi.User(me, id=int(user)))
			except ValueError:
				pass
	elif not options.all:
		raise(forumapi.OptionError("Users required."))
	
	graph_options = {
		"concentrate": True,
		#"fontname": "\"Courier\"",
	}
	if me.site.encoding == "ISO-8859-2":
		graph_options["charset"] = "latin1"
	
	graph = DotGraph.Digraph("friends")
	graph.append(DotGraph.AttrList(graph_options, subject="graph"))
	
	uid = 0
	while True:
		if users:
			user = users.pop(0)
		elif options.all:
			uid += 1
			user = forumapi.User(me, id=uid)
		else:
			print("Done fetching users.")
			break
		
		if options.max_user is not None and user.id > options.max_user:
			break
		
		add_user(graph, user, recursion=options.recursion, max_user=options.max_user)
	
	filename = "data/dot/" + "".join(random.sample(string.ascii_lowercase, random.randint(5, 10)))
	print("Filename: " + filename)
	
	f = open(filename, mode="w", encoding=me.site.encoding)
	f.write(graph.parse())
	f.close()
	print("Created graph text.")
	
	subprocess.call("dot -Tpng -O " + filename)
	print("Created graph image.")

def add_user(graph, user, recursion=0, max_user=None):
	if user._name and user.name in graph.data:
		# Already done
		return(None)
	
	print("User ID: {0}".format(user.id))
	try:
		user.get_profile(friends_pages="all")
	except forumapi.UserError as ex:
		if max_user:
			print(ex)
		else:
			raise
	
	if user._friends:
		left = DotGraph.Node(user.name)
		right = DotGraph.Subgraph(user.id, [DotGraph.Node(friend.name) for friend in user.friends])
		graph.append(DotGraph.Edge(graph, left, right))
		
		if recursion > 0:
			for friend in user.friends:
				add_user(graph, friend, recursion=recursion - 1)

if __name__ == "__main__":
	forumapi.run(main, options=settings, supported_types=["vbulletin"])
